using System;
using System.Collections.Generic;

namespace RexToy.Compiler.Lexical
{
    public abstract class LexicalParser<TTokenType, TStatusMatrix>
        where TStatusMatrix : StatusMatrixBase, new()
    {
        protected int _index;
        protected string _text;
        protected int _status;
        protected List<Token<TTokenType>> _tokens;
        protected TStatusMatrix _matrix;
        protected bool _keepSpaceChar;
        
        protected LexicalParser(bool keepSpaceChar = false)
        {
            _matrix = new TStatusMatrix();
            _matrix.TokenTerminate += this.AcceptLastToken;
            _keepSpaceChar = keepSpaceChar;
        }

        public abstract void SetParseContent(string text);

        protected char GetNextChar()
        {
            if (_index == _text.Length)
                return (char)0;
            else
            {
                return _text[_index++];
            }
        }

        protected char PeekNextChar()
        {
            if (_index == _text.Length)
                return (char)0;
            else
                return _text[_index];
        }

        protected Token<TTokenType> curr;
        public abstract List<Token<TTokenType>> Parse();
        protected abstract Token<TTokenType> CreateNewToken(int index);

        protected virtual void AcceptLastToken(object sender, LexicalParseEventArgs e)
        {
            string val = _keepSpaceChar ? curr.TokenValue : curr.TokenValue.Trim();
            if (val.Length != 0)//Note:throw zero length token away.
            {
                curr.EvalType(_status);
                _tokens.Add(curr);
            }

            curr = this.CreateNewToken(_index - 1);//Note:Next token begin.
            if (e.Ch != (char)0)
                curr.Add(e.Ch);
        }
    }
}
